#pragma once
#include "cinder/Rect.h"
#include "cinder/Color.h"
#include "cinder/Font.h"
#include "Layout/Alignment.h"
#include <memory>
#include <string>

namespace cxgui
{
using namespace std;
using namespace ci;
class Control : public enable_shared_from_this<Control>
{
public:
	Control();
	
	
	 /// Updates control logic but not layout	
	virtual void Update();


	/// Draws the control
	virtual void Draw();

	/// Assigns who is the parent of this control
	void SetParent(shared_ptr<Control> parent);

	/// Sets the background color
	void SetBackColor(ColorA color);

	/// Is called when the control's parent has changed
	virtual void OnParentChanged();

	/// Is called when the control's background has changed 
	virtual void OnBackColorChanged();	

	/// Returns the margin
	Rectf GetMargin() const;
	

	/// Returns the padding
	Rectf GetPadding() const;

	/// Returns the thickness of the border
	Rectf GetBorderThickness() const;

	/// Sets a margin to to the control
	void SetMargin(const Rectf& margin);

	void SetMargin(float left, float top, float right, float bottom);

	void SetMargin(float leftAndRight, float topAndBottom);

	void SetMargin(float all);

	/// Sets a padding to the control
	void SetPadding(const Rectf& padding);

	void SetPadding(float left, float top, float right, float bottom);

	void SetPadding(float leftAndRight, float topAndBottom);

	void SetPadding(float all);

	/// Sets the thickness of the control's border
	void SetBorderThickness(const Rectf& borderThickness);

	/// Returns the vertical alignment of the control
	VerticalAlignment GetVerticalAlignment() const;

	/// Returns the horizontal alignment of the control
	HorizontalAlignment GetHorizontalAlignment() const;

	/// Sets how the control is vertically aligned
	void SetVerticalAlignment(VerticalAlignment alignment);

	/// Sets how the control is horizontally aligned
	void SetHorizontalAlignment(HorizontalAlignment alignment);

	/// Gets the size that accommodates the control
	virtual Vec2f GetPreferedSize();

	/// Returns the client area where the control can draw itself
	Rectf GetClientRectangle() const;

	/// Sets the client area where the control can draw itself
	virtual void SetClientRectangle(const Rectf& rect);

	virtual bool IsLayoutDirty() const;

	virtual ~Control();
protected:	
	virtual void DrawBackground();
	virtual void DrawForeground();
	virtual void DrawBorder();
	virtual void GrowRectangle(Rectf& outRect, const Rectf& thickness);	
	virtual void ShrinkRectangle(Rectf& outRect, const Rectf& thickness);
	
	virtual void IsLayoutDirty(bool isDirty);
	virtual void OnIsLayoutDirtyChanged();
	virtual void OnClientRectangleChanged();

	// Utilities
	
	virtual Rectf CalculateClientArea(const Rectf& clientArea); /// Returns the client area where the control can draw itself
	Vec2f GetTextSize(const string& text);
	void GrowVect(Vec2f& outVect, const Rectf& thickness);


	// Fields

	Rectf _margin;
	Rectf _padding;
	Rectf _borderThickness;
	Rectf _clientRectangle; /// stores the area where the control can draw itself

	ColorA _borderColor;
	ColorA _backColor;
	ColorA _foreColor;
	shared_ptr<Control> _parent;
	
	bool _isLayoutDirty; /// Indicates whether the layout needs to be revalidated.
	Font _font;		
	bool _isEnabled;	
	VerticalAlignment _verticalAlignment;
	HorizontalAlignment _horizontalAlignment;
};
}